资料结构体
HiEasyX 中,几乎所有控件(除了部分控件的部分方法不会)都会要求你在调用他们的函数的时候提供一个资料结构体(Profile)。这么说可能不太好理解,我们依然是以上次的测试代码为例:
HX::WindowProfile windowProfile;
while (true) {
...
HX::Window(HXStr("Hello World!"), windowProfile);
...
}
我们只关注创建虚拟窗口部分的代码。这里就可以看到 HX::WindowProfile
这个结构体了。这便是 HiEasyX 中的资料结构体:
在 HiEasyX 中,你当通过 HX::Window
创建虚拟窗口再创建控件。当然,你可以创建多个窗口。
HX::WindowProfile
的结构体定义如下所示(当然你不需要记住这些定义,也不需要知道每个变量都是什么意思):
/**
* The profile for a window
*/
struct WindowProfile {
HXPoint Size = {300, 200};
// Set the size to a value less than 0(including 0) to put these setting unused
// The MinSize, if the user does not set a minimum value, it will be put as a value
// which can contain the folding icon of the window
HXPoint MinSize = {-1, -1};
HXPoint MaxSize = {-1, -1};
HXPoint LastSize = {0, 0};
HXPoint Position = {0, 0};
bool InDrag = false;
bool Folded = false;
bool InAllSize = false;
bool InRAllSize = false;
bool InWidthSize = false;
bool InRWidthSize = false;
bool InHeightSize = false;
bool InCursorStyling = false;
// Set this as false to disable the resizing of the window
bool Sizable = true;
// Set this as false to disable the moving of the window
bool Movable = true;
HXGInt DeltaX = 0;
HXGInt DeltaY = 0;
HXGInt OriginX = 0;
HXGInt OriginY = 0;
};
可以看到,这几乎包含一个窗口所需要的信息。包括其大小、位置、是否被在拉伸、是否在被拖拽、是否折叠等等。因此,资料结构体这个听上去比较高大上的东西,实际上就是控件的属性的集合。还不理解?更简单地说就是控件所需要的一切信息都会放在这个结构体中。如果你还是不理解,没关系,在后面的代码中你会逐渐对这个概念有一个深层次的理解。
在 HiEasyX 中资料结构体是用户读取、修改控件状态的唯一方法。
资料结构体的生命周期需要被严格把控,错误地规划资料结构体的生命周期会导致意料以外的错误结果。举个最简单的最容易犯的错误:
将资料结构体作为局部变量定义在渲染循环或其他局部空间中,例如:
while (true) {
HX::WindowProfile windowProfile;
...
HX::Window(HXStr("Hello World!"), windowProfile);
...
}
千万别这么做,这将会导致程序的功能发生异常,至于为什么会这样读者可以自行思考。简单来说,这么干相当于:每次绘制都要清空一次控件属性。
现在再去看测试代码中是如何创建按钮的:
static HX::ButtonProfile buttonProfile;
...
if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}
是不是瞬间好理解了?资料结构体 HX::ButtonProfile
的定义如下:
/**
* The profile for a button
*/
struct ButtonProfile {
bool OnHover = false;
bool OnPressed = false;
// When the mouse button clicked down and didn't get up, OnHold
// will be true
bool OnHold = false;
HXPoint Size = {-1, -1};
};
这意味着,你可以通过修改 HX::ButtonProfile::Size
来实现自定义按钮的大小,就像这样:
static HX::ButtonProfile buttonProfile;
// 将按钮大小设置为 300, 300
buttonProfile.Size = { 300, 300 };
...
if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}
也可以通过 HX::ButtonProfile::OnPressed
判断按钮是否按下,就像这样:
if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}
if (buttonProfile.OnHover) {
printf("你的鼠标现在正在按钮上方");
}
需要注意的是,资料结构体应该在创建控件前修改,创建控件后读取。请勿像这样使用资料结构体:
if (buttonProfile.OnHover) {
printf("你的鼠标现在正在按钮上方");
}
if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}
buttonProfile.Size = { 300, 300 };
这将会导致错误地结果。
当然,我知道尽管你已经了解了这些,可能依然对测试代码有很多疑问。HX::BeginSameLine
是什么?HX::Button
的返回值有什么意义?没关系,结下的文章就是要讨论这些。